package org.javaexpert.spaces.masterworker.worker;

import net.jini.core.transaction.server.TransactionManager;
import net.jini.space.JavaSpace;
import org.javaexpert.spaces.masterworker.TaskBag;
import org.javaexpert.spaces.masterworker.TaskExecutionException;
import org.javaexpert.spaces.util.CriticalSpaceException;
import org.javaexpert.spaces.util.SpaceUtils;
import org.javaexpert.spaces.util.TransactionTemplate;

import java.rmi.RemoteException;
import java.util.Random;


public class Worker {
    private JavaSpace space;
    private TransactionManager mgr;
    private TaskBag taskBag;

    public static void main(String[] args) throws Exception {
        Worker worker = new Worker();
        worker.startWork();
    }


    private void initTaskBag() {
        taskBag = null;
        long sleepTime = 1000;
        do {
            try {
                space = SpaceUtils.findSpace("mySpace", "localhost");
                mgr = SpaceUtils.findTransactionManager("localhost");
                taskBag = new TaskBag("bag1", space, new TransactionTemplate(mgr));
            } catch (Exception e) {
                System.err.printf("Error connecting to space - sleeping for %dsec, then retrying...", sleepTime / 1000);
                sleep(sleepTime);
                sleepTime *= 2;
                e.printStackTrace();
            }
        } while (taskBag == null);
    }

    private void sleep(long sleepTime) {
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e1) {
            throw new RuntimeException(e1);
        }
    }


    public void startWork() throws CriticalSpaceException {
        initTaskBag();
        int agentId = new Random().nextInt(1000);
        System.err.println("Agent " + agentId);
        System.err.println("*******************************");
        for (; ;) {
            try {
                taskBag.acceptAndRunTasks("Agent: " + agentId);
            } catch (CriticalSpaceException e) {
                if (e.getCause() instanceof RemoteException) {
                    initTaskBag();
                } else if (e.getCause() instanceof TaskExecutionException) {
                    System.err.println("Task failed " + e.getCause().getCause());
                } else {
                    throw e;
                }
            }
        }
    }
}
